#ifndef _PARSER_PARSER_H
#define _PARSER_PARSER_H

#include "common.h"
#include "vm.h"
#include "meta_obj.h"
#include "../compiler/compiler.h"

typedef enum 
{
    TOKEN_UNKNOWN, TOKEN_NUM, TOKEN_STRING, TOKEN_ID, TOKEN_INTERPOLATION,
    TOKEN_VAR, TOKEN_FUN, TOKEN_IF, TOKEN_ELSE, TOKEN_TRUE, TOKEN_FALSE, TOKEN_WHILE, TOKEN_FOR, TOKEN_BREAK,
                TOKEN_CONTINUE, TOKEN_RETURN, TOKEN_NULL,
    TOKEN_CLASS, TOKEN_THIS, TOKEN_STATIC, TOKEN_IS, TOKEN_SUPER, TOKEN_IMPORT,
    TOKEN_COMMA, TOKEN_COLON, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_LEFT_BRACKET, TOKEN_RIGHT_BRACKET,
                TOKEN_LEFT_BRACE, TOKEN_RIGHT_BRACE, TOKEN_DOT, TOKEN_DOT_DOT,
    TOKEN_ADD, TOKEN_SUB, TOKEN_MUL, TOKEN_DIV, TOKEN_MOD,
    TOKEN_ASSIGN,
    TOKEN_BIT_AND, TOKEN_BIT_OR, TOKEN_BIT_NOT, TOKEN_BIT_SHIFT_RIGHT, TOKEN_BIT_SHIFT_LEFT,
    TOKEN_LOGIC_AND, TOKEN_LOGIC_OR, TOKEN_LOGIC_NOT,
    TOKEN_EQUAL, TOKEN_NOT_EQUAL, TOKEN_GREATE, TOKEN_GREATE_EQUAL, TOKEN_LESS, TOKEN_LESS_EQUAL,
    TOKEN_QUESTION,
    TOKEN_EOF
} TokenType;

typedef struct 
{
    TokenType type;
    const char *start;
    uint32_t length;
    uint32_t lineNo;
    Value value; // 用于存储单词的值
} Token;

struct parser 
{
    const char *file;
    const char *source_code;
    const char *next_char_ptr;

    char cur_char;
    Token cur_token;
    Token pre_token;
    ObjModule *cur_module; // 当前正在编译的模块
    CompileUnit *cur_compileUnit; // 当前编译单元

    int interpolation_expect_right_parent_num;
    struct parser *parent; // 指定父parser
    VM *vm;
};

char look_ahead_char(Parser *parser);
static void get_next_char(Parser *parser);
void get_next_token(Parser *parser);
static bool match_next_char(Parser *parser, char expected_char);
bool match_token(Parser *parser, TokenType expected);
void consume_cur_token(Parser *parser, TokenType expected, const char *err_msg);
void consum_next_token(Parser *parser, TokenType expected, const char * err_msg);
void init_parser(VM *vm, Parser *parser, const char *file, const char *source_code, ObjModule *obj_module);
uint32_t get_byte_num_of_encode_utf8(int value);
uint8_t encode_utf8(uint8_t *buf, int value);

#endif